﻿using OkTool.Codec;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Numerics;
using System.Text;

namespace OkTool.Util
{
    public class HexUtil
    {
        /// <summary>
        /// 判断给定字符串是否为16进制数
        ///<para>如果是，需要使用对应数字类型对象的{@code decode}方法解码</para>
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsHexNumber(string value)
        {
            if (value.StartsWith("-"))
            {
                // issue#2875
                return false;
            }
            int index = 0;
            if (value.Substring(index).StartsWith("0x") || value.Substring(index).StartsWith("0X"))
            {
                index += 2;
            }
            else if (value.Substring(index).StartsWith("#"))
            {
                index++;
            }
            string hexValue = value.Substring(index);
            return int.TryParse(hexValue, System.Globalization.NumberStyles.HexNumber, null, out _);
        }

        /// <summary>
        /// 将字节数组转换为十六进制字符数组
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static char[] EncodeHex(byte[] data)
        {
            return EncodeHex(data, true);
        }

        /// <summary>
        /// 将字节数组转换为十六进制字符数组
        /// </summary>
        /// <param name="str"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static char[] EncodeHex(string str, Encoding encoding)
        {
            byte[] bytes = encoding.GetBytes(str);
            return EncodeHex(bytes, true);
        }

        /// <summary>
        /// 将字节数组转换为十六进制字符数组
        /// </summary>
        /// <param name="data"></param>
        /// <param name="toLowerCase"></param>
        /// <returns></returns>
        public static char[] EncodeHex(byte[] data, bool toLowerCase)
        {
            return (toLowerCase ? Base16Codec.CODEC_LOWER : Base16Codec.CODEC_UPPER).Encode(data);
        }

        /// <summary>
        /// 将字节数组转换为十六进制字符串
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string EncodeHexStr(byte[] data)
        {
            return EncodeHexStr(data, true);
        }

        /// <summary>
        /// 将字符串转换为十六进制字符串，结果为小写
        /// </summary>
        /// <param name="data"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string EncodeHexStr(string data, Encoding encoding)
        {
            byte[] bytes = encoding.GetBytes(data);
            return EncodeHexStr(bytes, true);
        }

        /// <summary>
        /// 将字符串转换为十六进制字符串，结果为小写，默认编码是UTF-8
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string EncodeHexStr(string data)
        {
            return EncodeHexStr(data, Encoding.UTF8);
        }

        /// <summary>
        /// 将字节数组转换为十六进制字符串
        /// </summary>
        /// <param name="data"></param>
        /// <param name="toLowerCase"></param>
        /// <returns></returns>
        public static string EncodeHexStr(byte[] data, bool toLowerCase)
        {
            return new string(EncodeHex(data, toLowerCase));
        }

        /// <summary>
        /// 将十六进制字符数组转换为字符串，默认编码UTF-8
        /// </summary>
        /// <param name="hexStr"></param>
        /// <returns></returns>
        public static string DecodeHexStr(string hexStr)
        {
            return DecodeHexStr(hexStr, Encoding.UTF8);
        }
        /// <summary>
        /// 将十六进制字符数组转换为字符串
        /// </summary>
        /// <param name="hexStr">十六进制String</param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string DecodeHexStr(string hexStr, Encoding encoding)
        {
            if (string.IsNullOrEmpty(hexStr))
            {
                return hexStr;
            }
            return encoding.GetString(DecodeHex(hexStr));
        }

        /// <summary>
        /// 将十六进制字符数组转换为字符串
        /// </summary>
        /// <param name="hexData"></param>
        /// <param name="encoding">编码</param>
        /// <returns></returns>
        public static string DecodeHexStr(char[] hexData, Encoding encoding)
        {
            return encoding.GetString(DecodeHex(hexData));
        }


        /// <summary>
        /// 将十六进制字符数组转换为字节数组
        /// </summary>
        /// <param name="hexData"></param>
        /// <returns></returns>
        public static byte[] DecodeHex(char[] hexData)
        {
            return DecodeHex(new string(hexData));
        }

        /// <summary>
        /// 将十六进制字符数组转换为字节数组
        /// </summary>
        /// <param name="hexStr">十六进制字符串</param>
        /// <returns></returns>
        public static byte[] DecodeHex(string hexStr)
        {
            return Base16Codec.CODEC_LOWER.Decode(hexStr);
        }

        /// <summary>
        ///  将{@link Color}编码为Hex形式
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        public static string EncodeColor(System.Drawing.Color color)
        {
            return EncodeColor(color, "#");
        }

        /// <summary>
        /// 将{@link Color}编码为Hex形式
        /// </summary>
        /// <param name="color"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        public static string EncodeColor(System.Drawing.Color color, string prefix)
        {
            StringBuilder builder = new StringBuilder(prefix);
            builder.Append(color.R.ToString("X2"));
            builder.Append(color.G.ToString("X2"));
            builder.Append(color.B.ToString("X2"));
            return builder.ToString();
        }

        /// <summary>
        /// 将Hex颜色值转为
        /// </summary>
        /// <param name="hexColor"></param>
        /// <returns></returns>
        public static Color DecodeColor(string hexColor)
        {
            int argb = Int32.Parse(hexColor.Replace("#", ""), System.Globalization.NumberStyles.HexNumber);
            return Color.FromArgb(argb);
        }

        /// <summary>
        /// 将指定int值转换为Unicode字符串形式，常用于特殊字符（例如汉字）转Unicode形式
        ///<para> 转换的字符串如果u后不足4位，则前面用0填充，例如：'你' =》'\u4f60'</para>
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToUnicodeHex(int value)
        {
            StringBuilder builder = new StringBuilder(6);
            builder.Append("\\u");
            string hex = value.ToString("X4");
            builder.Append(hex);
            return builder.ToString();
        }

        /// <summary>
        /// 将指定char值转换为Unicode字符串形式，常用于特殊字符（例如汉字）转Unicode形式
        ///<para> 转换的字符串如果u后不足4位，则前面用0填充，例如：'你' =》'\u4f60'</para>
        /// </summary>
        /// <param name="ch"></param>
        /// <returns></returns>
        public static string ToUnicodeHex(char ch)
        {
            return Base16Codec.CODEC_LOWER.ToUnicodeHex(ch);
        }

        /// <summary>
        /// 转为16进制字符串
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToHex(int value)
        {
            return value.ToString("X");
        }

        /// <summary>
        /// 16进制字符串转为int
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int HexToInt(string value)
        {
            return System.Convert.ToInt32(value, 16);
        }

        /// <summary>
        /// 转为16进制字符串
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToHex(long value)
        {
            return value.ToString("X");
        }

        /// <summary>
        /// 16进制字符串转为long
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long HexToLong(string value)
        {
            return System.Convert.ToInt64(value, 16);
        }

        /// <summary>
        /// 将byte值转为16进制并添加到{@link StringBuilder}中
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="b"></param>
        /// <param name="toLowerCase"></param>
        public static void AppendHex(StringBuilder builder, byte b, bool toLowerCase)
        {
            (toLowerCase ? Base16Codec.CODEC_LOWER : Base16Codec.CODEC_UPPER).AppendHex(builder, b);
        }

        /// <summary>
        /// Hex（16进制）字符串转为BigInteger
        /// </summary>
        /// <param name="hexStr"></param>
        /// <returns></returns>
        public static BigInteger? ToBigInteger(string hexStr)
        {
            if (hexStr == null)
            {
                return null;
            }
            return BigInteger.Parse(hexStr, System.Globalization.NumberStyles.HexNumber);
        }

        /// <summary>
        /// 格式化Hex字符串，结果为每2位加一个空格，类似于：
        ///<para>e8 8c 67 03 80 cb 22 00 95 26 8f</para>
        /// </summary>
        /// <param name="hexStr"></param>
        /// <returns>格式化后的字符串</returns>
        public static string Format(string hexStr)
        {
            int length = hexStr.Length;
            StringBuilder builder = new StringBuilder(length + length / 2);
            builder.Append(hexStr[0]).Append(hexStr[1]);
            for (int i = 2; i < length - 1; i += 2)
            {
                builder.Append(' ').Append(hexStr[i]).Append(hexStr[i + 1]);
            }
            return builder.ToString();
        }
    }
}
